package com.easy.frame.servers.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.frame.base.api.pojo.PageDTO;
import com.easy.frame.base.api.pojo.PageVO;
import com.easy.frame.base.basic.constant.DbConstants;
import com.easy.frame.base.basic.constant.NumberConstants;
import com.easy.frame.base.basic.exception.ServiceException;
import com.easy.frame.base.basic.msg.ExceptionMsg;
import com.easy.frame.base.basic.pojo.MenuContent;
import com.easy.frame.base.basic.pojo.MenuContentList;
import com.easy.frame.base.basic.pojo.vo.BaseTreeVO;
import com.easy.frame.base.basic.util.AuthUtil;
import com.easy.frame.base.service.mp.page.PageProxy;
import com.easy.frame.base.service.tree.TreeHandler;
import com.easy.frame.base.service.tree.TreeUtil;
import com.easy.frame.servers.sys.dto.SysMenusCustomDTO;
import com.easy.frame.servers.sys.entity.SysMenu;
import com.easy.frame.servers.sys.entity.SysMenusCustom;
import com.easy.frame.servers.sys.mapper.menu.SysMenuMapper;
import com.easy.frame.servers.sys.mapper.menu.SysMenusCustomMapper;
import com.easy.frame.servers.sys.service.SysMenusCustomService;
import com.easy.frame.servers.sys.vo.SysMenusCustomVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自定义菜单表 服务实现类
 *
 * @author tp
 * @since 2021-01-05
 */
@Service
@Slf4j
public class SysMenusCustomServiceImpl extends ServiceImpl<SysMenusCustomMapper, SysMenusCustom> implements SysMenusCustomService {

    @Resource
    SysMenuMapper sysMenuMapper;

    @Override
    public BaseTreeVO getEquTypeTree(int enabled, String equName) {
        List<SysMenusCustom> sysMenusCustomList = baseMapper.getEquTypeTree
                (enabled);
        if (StringUtils.isEmpty(sysMenusCustomList)) {
            return null;
        }
        List<SysMenusCustom> resultList;
        if (!StringUtils.isEmpty(equName)) {
            List<SysMenusCustom> collect = sysMenusCustomList.stream()
                    .filter(s -> s.getName().contains(equName))
                    .collect(Collectors.toList());
            resultList = new ArrayList<>(collect);
            collect.forEach(s -> this.getParent(s, sysMenusCustomList, resultList));
        } else {
            resultList = sysMenusCustomList;
        }
        //set方式进行去重
        return TreeHandler.defaultInstance().getTree(new HashSet<>(resultList));
    }

    @Override
    public SysMenusCustomVO clickAddEqu(Integer parentEquId) {
        SysMenusCustomVO sysMenusCustomVO = new SysMenusCustomVO();
        //首先默认为第一层级的分类
        int level = 1;
        SysMenusCustomVO parentMenus = new SysMenusCustomVO();
        if (!StringUtils.isEmpty(parentEquId)) {
            parentMenus = baseMapper.selectParentEquById(parentEquId);
            sysMenusCustomVO.setCode(parentMenus.getCode());
            sysMenusCustomVO.setParentPath(parentMenus.getPath());
            sysMenusCustomVO.setName(parentMenus.getName());
            level = parentMenus.getLevel() + 1;
        }
        Integer maxSeq = baseMapper.selectMaxSeq(parentMenus.getPath(), level);
        sysMenusCustomVO.setOrderNum(StringUtils.isEmpty(maxSeq) ? 10 : maxSeq / 10 * 10 + 10);
        sysMenusCustomVO.setEnabled(1);
        return sysMenusCustomVO;
    }

    /**
     * 批量添加节点对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBatch(List<SysMenusCustomDTO> addDTOList, String parentPath) {
        List<SysMenusCustom> sysMenusCustomList = new ArrayList<>();
        addDTOList.forEach(s -> {
            s.setCode(setCode(s.getCode()));
            //校验该code是否存在；
            SysMenusCustom sysMenusCustomName = baseMapper.checkEquName
                    (s.getName(), parentPath);
            if (!StringUtils.isEmpty(sysMenusCustomName)) {
                log.info("新增分类名【{}】已存在，请修改后提交", s.getName());
                throw new ServiceException(ExceptionMsg.ADD_ALREADY_EXISTS,s.getName());
            }
            //添加
            SysMenusCustom entity = new SysMenusCustom();
            BeanUtils.copyProperties(s, entity);
            //设置本身路径，通过父路径可能含有多个，但是如果没有的话就说明这个第一个
            String maxPath = baseMapper.selectMaxPath(parentPath);
            setEntity(entity, s, maxPath);
            entity.setParentPath(parentPath);
            entity.setIsOriginal(false);
            entity.setIsBaseApp(DbConstants.DEFAULT_YES);
            sysMenusCustomList.add(entity);
        });
        saveBatch(sysMenusCustomList);

        //添加子分类之后，设置父节点的叶子节点为不是叶子节点
        if (!StringUtils.isEmpty(sysMenusCustomList.get(0).getParentPath())) {
            SysMenusCustom temp = new SysMenusCustom();
            temp.setLeafNode(false);
            temp.setPath(sysMenusCustomList.get(0).getParentPath());
            baseMapper.updateLeafNode(temp);
        }
    }

    @Override
    public void updateParentDelete(Long id) {
        SysMenusCustom sysMenusCustom = baseMapper.selectById(id);
        if (StringUtils.isEmpty(sysMenusCustom)) {
            throw new ServiceException("节点不存在，请刷新后再试！");
        }
        sysMenusCustom.setDeleted(NumberConstants.CONSTANTS_ONE);
        sysMenusCustom.setUpdateBy(AuthUtil.getCurrentUserId());
        baseMapper.updateById(sysMenusCustom);
        List<SysMenusCustom> sysMenusCustomList = baseMapper
                .selectList(new LambdaQueryWrapper<SysMenusCustom>()
                        .eq(SysMenusCustom::getParentPath, sysMenusCustom.getPath())
                        .eq(SysMenusCustom::getDeleted, DbConstants.DEFAULT_NO)
                );
        sysMenusCustomList.forEach(s -> {
            s.setDeleted(DbConstants.DEFAULT_YES);
        });
        updateBatchById(sysMenusCustomList);
    }

    public String setCode(String code){
        return code + ":" + new Random().nextInt(99999);
    }

    public void checkName(SysMenusCustomDTO s) {
        SysMenusCustom sysMenusCustomName = baseMapper.checkEquName
                (s.getName(), s.getParentPath());
        if (!StringUtils.isEmpty(sysMenusCustomName)) {
            throw new ServiceException(ExceptionMsg.ADD_ALREADY_EXISTS,s.getName());
        }
    }

    public void setEntity(SysMenusCustom entity, SysMenusCustomDTO s, String maxPath) {
        if (StringUtils.isEmpty(maxPath)) {
            entity.setPath(TreeUtil.getFirstChildPath(entity.getParentPath()));
        } else {
            entity.setPath(TreeUtil.getNextChildPath(maxPath));
        }
        entity.setName(s.getName());
        entity.setLevel(TreeUtil.getLevel(entity.getPath()));
        entity.setCreateTime(new Date());
        entity.setLeafNode(true);
        entity.setIsRefresh(false);
        entity.setCreateBy(AuthUtil.getCurrentUserId());
        entity.setUpdateBy(AuthUtil.getCurrentUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized SysMenusCustom add(SysMenusCustomDTO addDTO) {
        //校验该code是否存在；
        checkName(addDTO);
        SysMenusCustom sysMenusCustomName = baseMapper.checkEquName
                (addDTO.getName(), addDTO.getParentPath());
        if (!StringUtils.isEmpty(sysMenusCustomName)) {
            throw new ServiceException(ExceptionMsg.ADD_ALREADY_EXISTS,addDTO.getName());
        }
        //添加
        SysMenusCustom entity = new SysMenusCustom();
        BeanUtils.copyProperties(addDTO, entity);
        //设置本身路径，通过父路径可能含有多个，但是如果没有的话就说明这个第一个
        String maxPath = baseMapper.selectMaxPath(entity.getParentPath());
        setEntity(entity, addDTO, maxPath);
        baseMapper.insert(entity);

        //添加子分类之后，设置父节点的叶子节点为不是叶子节点
        if (!StringUtils.isEmpty(entity.getParentPath())) {
            SysMenusCustom temp = new SysMenusCustom();
            temp.setLeafNode(false);
            temp.setPath(entity.getParentPath());
            baseMapper.updateLeafNode(temp);
        }
        return entity;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized SysMenusCustom modify(SysMenusCustomDTO entity) {
        //校验名称：同层级的不可以重复，不同层级的重复可以重复
        List<SysMenusCustom> subOptList;
        if (!StringUtils.isEmpty(entity.getParentPath())) {
            subOptList = baseMapper.selectEquipmentTypebyName(
                    entity.getName(), entity.getParentPath());
        } else {
            subOptList = baseMapper.selectEquipmentTypebyLevel(
                    entity.getName(), entity.getLevel());
        }
        boolean b = false;
        if (subOptList.size() >= 1) {
            b = subOptList.get(0).getId().equals(entity.getId());
        }
        if (subOptList.size() > 0 && !b) {
            throw new ServiceException(ExceptionMsg.ADD_ALREADY_EXISTS,entity.getName());
        }

        SysMenusCustom oldSysMenusCustom = baseMapper.selectById(entity.getId());
        boolean changeToDisable = (oldSysMenusCustom.getEnabled() == 1) && (entity.getEnabled() == 0);
        List<SysMenusCustom> sysMenusCustom = baseMapper.selectHaveChild(oldSysMenusCustom.getPath());
        boolean hasEnableChild = StringUtils.isEmpty(sysMenusCustom);
        if (!entity.getLeafNode() && changeToDisable && hasEnableChild) {
            throw new ServiceException("该设备设施分项下存在有效的子分项，不允许失效");
        }

        boolean changeToEnable = (oldSysMenusCustom.getEnabled() == 0) && (entity.getEnabled() == 1);
        SysMenusCustom sysMenusCustomParent =
                baseMapper.selectEquipmentTypeNotEnable(oldSysMenusCustom.getPath());
        //将失效的能设施分项改为有效时，需校验其所有父级设施分项是否有效，当存在失效的父级设施分项时，提示“存在失效的父级分项，请先将修改父级分项为有效”；
        if (changeToEnable && !StringUtils.isEmpty(entity.getParentPath()) && StringUtils.isEmpty(sysMenusCustomParent)) {
            throw new ServiceException("存在失效的父级分项，请先将修改父级分项为有效");
        }
        SysMenusCustom sysEntity = new SysMenusCustom();
        BeanUtils.copyProperties(entity, sysEntity);
        sysEntity.setUpdateBy(AuthUtil.getCurrentUserId());
        baseMapper.updateById(sysEntity);
        return sysEntity;
    }

    @Override
    public SysMenusCustomVO selectById(Long id) {
        SysMenusCustomVO sysMenusCustomVO = baseMapper.selectVoById(id);
        if (StringUtils.isEmpty(sysMenusCustomVO)) {
            return null;
        }
        sysMenusCustomVO.setUpdateBy(AuthUtil.getCurrentUserId());
        sysMenusCustomVO.setParentPathName(NumberConstants.NONE);
        if (!StringUtils.isEmpty(sysMenusCustomVO)) {
            SysMenusCustom sysMenusCustomParent = baseMapper.
                    selectEquipmentTypeByParentpath(sysMenusCustomVO.getParentPath());
            if (!StringUtils.isEmpty(sysMenusCustomParent)) {
                sysMenusCustomVO.setParentPathName(sysMenusCustomParent.getName());
                sysMenusCustomVO.setParentId(sysMenusCustomParent.getId());
            }
        }
        return sysMenusCustomVO;
    }

    @Override
    public int countById(Long id) {
        return baseMapper.countById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDelete(Long id) {
        SysMenusCustom sysMenusCustom = baseMapper.selectById(id);
        if (StringUtils.isEmpty(sysMenusCustom)) {
            throw new ServiceException(ExceptionMsg.ADD_ALREADY_EXISTS,id);
        }
        if (!sysMenusCustom.getLeafNode()) {
            throw new ServiceException("不是叶子节点，不允许直接删除，请先删除其子节点！");
        }
        sysMenusCustom.setDeleted(NumberConstants.CONSTANTS_ONE);
        sysMenusCustom.setUpdateBy(AuthUtil.getCurrentUserId());
        sysMenusCustom.setIsAdd(false);
        baseMapper.updateById(sysMenusCustom);

        // 若删除的不是第一层级，则需更新其父节点为叶子节点
        if (!sysMenusCustom.getLevel().equals(NumberConstants.CONSTANTS_ONE)) {
            int count = baseMapper.selectByParentPath(sysMenusCustom.getParentPath());
            if (count == 0) {
                SysMenusCustom custom = new SysMenusCustom();
                custom.setPath(sysMenusCustom.getParentPath());
                custom.setLeafNode(true);
                baseMapper.updateByParentPath(custom);
            }
        }
    }

    /**
     * 更新自定义菜单列表后，点击刷新权限按钮同步菜单menu表单，并返回提示内容（目的就是更换之后自定义菜单之后，同步到菜单表）
     * 1.查询出数据库中所有的有效菜单节点
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int menuAuthRefresh() {
        List<SysMenusCustom> sysMenusCustomList =
                baseMapper.selectList(new LambdaQueryWrapper<SysMenusCustom>()
                .eq(SysMenusCustom::getIsRefresh, false)
                .select());
        if (StringUtils.isEmpty(sysMenusCustomList)) {
            return 200;
        }
        sysMenusCustomList.forEach(s -> {
            SysMenu sysMenu = new SysMenu();
            BeanUtils.copyProperties(s, sysMenu);
            MenuContent menuContent = new MenuContent();
            menuContent.setKey("read");
            MenuContentList menuContents = new MenuContentList();
            menuContents.add(menuContent);
            sysMenu.setOperations(menuContents);
            sysMenuMapper.insert(sysMenu);
            s.setIsRefresh(true);
            s.setUpdateTime(new Date());
            baseMapper.updateById(s);
        });
        return 201;
    }

    @Override
    public PageVO<SysMenusCustomVO> menuListByName(PageDTO<SysMenusCustomDTO> pageDTO) {
        return PageProxy.proxy(baseMapper::selectForPage, pageDTO);
    }


    /**
     * 获取设备设施表树状结构 - 获取父级
     */
    private void getParent(SysMenusCustom subdivisionOption, List<SysMenusCustom> list, List<SysMenusCustom> resultList) {
        String parentPath = subdivisionOption.getParentPath();
        if (StringUtils.isEmpty(parentPath)) {
            return;
        }
        for (SysMenusCustom s : list) {
            if (parentPath.equals(s.getPath())) {
                resultList.add(s);
                if (!StringUtils.isEmpty(parentPath)) {
                    getParent(s, list, resultList);
                }
            }
        }
    }
}
